import 'package:flutter/foundation.dart';

/// 缓存错误类型
enum CacheErrorType {
  network,
  storage,
  permission,
  timeout,
  invalidUrl,
  unknown,
}

/// 缓存错误
class CacheError {
  final String code;
  final String message;
  final String? url;
  final DateTime timestamp;
  final CacheErrorType type;
  final bool isRetryable;
  final Map<String, dynamic>? details;

  const CacheError({
    required this.code,
    required this.message,
    this.url,
    required this.timestamp,
    required this.type,
    required this.isRetryable,
    this.details,
  });

  factory CacheError.network(String message, {String? url, Map<String, dynamic>? details}) {
    return CacheError(
      code: 'NETWORK_ERROR',
      message: message,
      url: url,
      timestamp: DateTime.now(),
      type: CacheErrorType.network,
      isRetryable: true,
      details: details,
    );
  }

  factory CacheError.storage(String message, {String? url, Map<String, dynamic>? details}) {
    return CacheError(
      code: 'STORAGE_ERROR',
      message: message,
      url: url,
      timestamp: DateTime.now(),
      type: CacheErrorType.storage,
      isRetryable: false,
      details: details,
    );
  }

  factory CacheError.timeout(String message, {String? url, Map<String, dynamic>? details}) {
    return CacheError(
      code: 'TIMEOUT_ERROR',
      message: message,
      url: url,
      timestamp: DateTime.now(),
      type: CacheErrorType.timeout,
      isRetryable: true,
      details: details,
    );
  }

  factory CacheError.invalidUrl(String message, {String? url, Map<String, dynamic>? details}) {
    return CacheError(
      code: 'INVALID_URL',
      message: message,
      url: url,
      timestamp: DateTime.now(),
      type: CacheErrorType.invalidUrl,
      isRetryable: false,
      details: details,
    );
  }

  factory CacheError.unknown(String message, {String? url, Map<String, dynamic>? details}) {
    return CacheError(
      code: 'UNKNOWN_ERROR',
      message: message,
      url: url,
      timestamp: DateTime.now(),
      type: CacheErrorType.unknown,
      isRetryable: true,
      details: details,
    );
  }

  @override
  String toString() => 'CacheError(code: $code, message: $message, url: $url, type: $type, isRetryable: $isRetryable)';
}

/// 错误处理策略
abstract class ErrorHandlingStrategy {
  Future<void> handleError(CacheError error);
}

/// 默认错误处理策略
class DefaultErrorHandlingStrategy implements ErrorHandlingStrategy {
  @override
  Future<void> handleError(CacheError error) async {
    debugPrint('CacheError: ${error.toString()}');
    
    // 根据错误类型执行不同的处理逻辑
    switch (error.type) {
      case CacheErrorType.network:
        await _handleNetworkError(error);
        break;
      case CacheErrorType.storage:
        await _handleStorageError(error);
        break;
      case CacheErrorType.timeout:
        await _handleTimeoutError(error);
        break;
      case CacheErrorType.invalidUrl:
        await _handleInvalidUrlError(error);
        break;
      case CacheErrorType.permission:
        await _handlePermissionError(error);
        break;
      case CacheErrorType.unknown:
        await _handleUnknownError(error);
        break;
    }
  }

  Future<void> _handleNetworkError(CacheError error) async {
    debugPrint('处理网络错误: ${error.message}');
    // 可以在这里实现网络错误的特殊处理逻辑
  }

  Future<void> _handleStorageError(CacheError error) async {
    debugPrint('处理存储错误: ${error.message}');
    // 可以在这里实现存储错误的特殊处理逻辑
  }

  Future<void> _handleTimeoutError(CacheError error) async {
    debugPrint('处理超时错误: ${error.message}');
    // 可以在这里实现超时错误的特殊处理逻辑
  }

  Future<void> _handleInvalidUrlError(CacheError error) async {
    debugPrint('处理无效URL错误: ${error.message}');
    // 可以在这里实现无效URL错误的特殊处理逻辑
  }

  Future<void> _handlePermissionError(CacheError error) async {
    debugPrint('处理权限错误: ${error.message}');
    // 可以在这里实现权限错误的特殊处理逻辑
  }

  Future<void> _handleUnknownError(CacheError error) async {
    debugPrint('处理未知错误: ${error.message}');
    // 可以在这里实现未知错误的特殊处理逻辑
  }
}

/// 缓存错误处理器
class CacheErrorHandler {
  static CacheErrorHandler? _instance;
  static CacheErrorHandler get instance => _instance ??= CacheErrorHandler._();

  CacheErrorHandler._();

  ErrorHandlingStrategy _strategy = DefaultErrorHandlingStrategy();
  final List<CacheError> _errorHistory = [];
  static const int maxErrorHistory = 100;

  /// 设置错误处理策略
  void setStrategy(ErrorHandlingStrategy strategy) {
    _strategy = strategy;
  }

  /// 处理错误
  Future<void> handleError(CacheError error) async {
    // 记录错误历史
    _errorHistory.add(error);
    if (_errorHistory.length > maxErrorHistory) {
      _errorHistory.removeAt(0);
    }

    // 使用策略处理错误
    await _strategy.handleError(error);
  }

  /// 从异常创建CacheError
  CacheError createErrorFromException(dynamic exception, {String? url}) {
    final message = exception.toString();
    
    if (message.contains('network') || message.contains('connection')) {
      return CacheError.network(message, url: url);
    } else if (message.contains('timeout')) {
      return CacheError.timeout(message, url: url);
    } else if (message.contains('storage') || message.contains('disk')) {
      return CacheError.storage(message, url: url);
    } else if (message.contains('invalid') && message.contains('url')) {
      return CacheError.invalidUrl(message, url: url);
    } else {
      return CacheError.unknown(message, url: url);
    }
  }

  /// 获取错误历史
  List<CacheError> getErrorHistory() {
    return List.unmodifiable(_errorHistory);
  }

  /// 获取错误统计
  Map<String, dynamic> getErrorStatistics() {
    final total = _errorHistory.length;
    final byType = <CacheErrorType, int>{};
    final retryableCount = _errorHistory.where((e) => e.isRetryable).length;

    for (final error in _errorHistory) {
      byType[error.type] = (byType[error.type] ?? 0) + 1;
    }

    return {
      'total': total,
      'retryable': retryableCount,
      'nonRetryable': total - retryableCount,
      'byType': byType.map((k, v) => MapEntry(k.name, v)),
    };
  }

  /// 清理错误历史
  void clearErrorHistory() {
    _errorHistory.clear();
    debugPrint('CacheErrorHandler: 错误历史已清理');
  }
}
